home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d16 / winvn060.arc / WVUTIL.C < prev   
C/C++ Source or Header  |  1991-07-01  |  21KB  |  629 lines

  1. /*-- WVUTIL.C -- File containing utility routines.
  2.  */
  3.  
  4. #include "windows.h"
  5. #include "wvglob.h"
  6. #include "winvn.h"
  7. #ifndef MAC
  8. #include "winundoc.h"
  9. #include <ctype.h>
  10. #endif
  11.  
  12. /*--- function GetNum --------------------------------------------
  13.  *
  14.  *  Cracks off a positive integer number from a string.
  15.  *
  16.  *  Entry    *ptr  is the character position to start scanning
  17.  *                 for an integer
  18.  *
  19.  *  Exit     *ptr  is the character position at which we stopped
  20.  *                 scanning (because of a non-digit).
  21.  *           *num  is the cracked off number.
  22.  *           Returns TRUE iff we got a number.
  23.  */
  24. BOOL
  25. GetNum(ptr,num)
  26. char **ptr;
  27. long int *num;
  28. {
  29.    BOOL gotit = FALSE;
  30.  
  31.    /* Skip initial spaces                                            */
  32.  
  33.    while((**ptr) && **ptr == ' ') (*ptr)++;
  34.  
  35.    *num = 0;
  36.    while(**ptr && isdigit(**ptr)) {
  37.       *num = 10*(*num) + (**ptr - '0');
  38.       gotit = TRUE;
  39.       (*ptr)++;
  40.    }
  41.    return(gotit);
  42. }
  43.  
  44. /*-- function StrToRGB -------------------------------------------------
  45.  *
  46.  *  Takes an ASCII string of the form "r,g,b" where r, g, and b are
  47.  *  decimal ASCII numbers, and converts it to an RGB color number.
  48.  */
  49. DWORD
  50. StrToRGB(cstring)
  51. char *cstring;
  52. {
  53.    BYTE red, green, blue;
  54.    long int lred, lgreen, lblue;
  55.  
  56.    GetNum(&cstring,&lred);
  57.    cstring++;
  58.    GetNum(&cstring,&lgreen);
  59.    cstring++;
  60.    GetNum(&cstring,&lblue);
  61.    red = (BYTE) lred; green = (BYTE) lgreen; blue = (BYTE) lblue;
  62. #ifndef MAC
  63.    return(RGB(red,green,blue));
  64. #else
  65.    return((DWORD) red+green+blue);
  66. #endif
  67. }
  68.  
  69. /*-- function DoCommInput ---------------------------------------
  70.  *
  71.  *
  72.  */
  73. void
  74. DoCommInput()
  75. {
  76.    int ch;
  77.  
  78.    while((ch = MRRReadComm()) >= 0) {
  79.       /*   putchar(ch); */  /* debug */
  80.       if(ch == IgnoreCommCh) {
  81.       } else if(ch == EOLCommCh) {
  82.          *CommLinePtr = '\0';
  83.          DoCommState();
  84.          CommLinePtr = CommLineIn;
  85.       } else {
  86.          *(CommLinePtr++) = (char) ch;
  87.          if(CommLinePtr == CommLineLWAp1) CommLinePtr--;
  88.       }
  89.    }
  90. }
  91.  
  92. /*-- function DoCommState ----------------------------------------------
  93.  *
  94.  *  Function to implement an FSA to process incoming lines from
  95.  *  the server.
  96.  *  This function is called once for each line from the server.
  97.  *
  98.  *    Entry    CommLineIn  is a zero-terminated line received from
  99.  *                         the server.
  100.  *             CommState   is the current state of the FSA.
  101.  */
  102. void
  103. DoCommState()
  104. {
  105.    TypLine far *LinePtr;
  106.    TypBlock far *BlockPtr;
  107.    TypArticle *artptr;
  108.    TypArticle far *MyArtPtr;
  109.    HANDLE hBlock;
  110.    HWND hWndPostEdit;
  111.    unsigned int Offset;
  112.    TypLineID MyLineID;
  113.    int retcode;
  114.    int ih, found;
  115.    unsigned int estnum;
  116.    long int first,last;
  117.    long int artnum;
  118.    int lineord;
  119.    int mylen;
  120.    int col;
  121.    int mbcode;
  122.    BOOL done=FALSE;
  123.    BOOL dolist;
  124.    char group[MAXINTERNALLINE];
  125.    char mybuf[MAXINTERNALLINE];
  126.    char artline[MAXINTERNALLINE];
  127.    char *cptr, *cdest;
  128.    char far *lpsz;
  129.    HDC hDC;
  130.    long int PrevHighArt;
  131.  
  132.    if(CommDoc) {
  133.  
  134.       switch(CommState) {
  135.          case ST_NONE:
  136.             break;
  137.  
  138.          case ST_ESTABLISH_COMM:
  139.             retcode = 0;
  140.             sscanf(CommLineIn,"%u",&retcode);
  141.             if(retcode == 500) {
  142.                dolist = DoList;
  143.                if(dolist == ID_DOLIST_ASK-ID_DOLIST_BASE) {
  144.                   dolist = DialogBox(hInst,"WinVnDoList",hWndConf,lpfnWinVnDoListDlg);
  145.                }
  146.                if(dolist) {
  147.                   StartList();
  148.                } else {
  149.                   CommState = ST_NONE;
  150.                   CommBusy = FALSE;
  151.                   Initializing = INIT_DONE;
  152.                }
  153.  
  154.                InvalidateRect(hWndConf,NULL,FALSE);
  155.             }
  156.             break;
  157.  
  158.          case ST_LIST_RESP:
  159.             retcode = 0;
  160.             sscanf(CommLineIn,"%d",&retcode);
  161.             if(retcode != 215) break;
  162.             CommState = ST_LIST_GROUPLINE;
  163.             RcvLineCount = 0;
  164.             break;
  165.  
  166.          case ST_LIST_GROUPLINE:
  167.             if(strcmp(CommLineIn,".") == 0) {
  168.                CommState = ST_NONE;
  169.                CommBusy = FALSE;
  170.                Initializing = INIT_DONE;
  171.                InvalidateRect(hWndConf,NULL,FALSE);
  172.  
  173.                ProcEndList();
  174.             } else {
  175.                ProcListLine((unsigned char *)CommLineIn);
  176.             }
  177.             break;
  178.  
  179.          case ST_GROUP_RESP:
  180.             retcode = 0;
  181.             sscanf(CommLineIn,"%u %u %ld %ld %s",&retcode,&estnum,&first,&last,group);
  182.             if(retcode < 100) break;
  183.             LockLine(CommDoc->hParentBlock,CommDoc->ParentOffset,CommDoc->ParentLineID,&BlockPtr,&LinePtr);
  184.             (((TypGroup far *) ((char far *) LinePtr + sizeof(TypLine)) )->ServerEstNum) = estnum;
  185.             (((TypGroup far *) ((char far *) LinePtr + sizeof(TypLine)) )->ServerFirst ) = first;
  186.             (((TypGroup far *) ((char far *) LinePtr + sizeof(TypLine)) )->ServerLast  ) = last;
  187.             GlobalUnlock(BlockPtr->hCurBlock);
  188.             /* Note:  the output from the GROUP command evidently
  189.              * can't always be relied upon; there may be more articles
  190.              * beyond the last article it reports.  So, I will just
  191.              * use a very large last article number here.
  192.              */
  193.             mylen = sprintf(mybuf,"XHDR subject %ld-%ld\r",first,999999L);
  194.             PutCommLine(mybuf,mylen);
  195.             CommState = ST_XHDR_RESP;
  196.             break;
  197.  
  198.          case ST_XHDR_RESP:
  199.             retcode = 0;
  200.             sscanf(CommLineIn,"%d",&retcode);
  201.             if(retcode < 100) break;
  202.             CommState = ST_XHDR_SUBJ;
  203.             break;
  204.  
  205.          case ST_XHDR_SUBJ:
  206.             if(strcmp(CommLineIn,".") == 0) {
  207.                CommState = ST_IN_GROUP;
  208.                CommBusy = FALSE;
  209.                /* Fetch this group's line in NetDoc so we can get the
  210.                 * group's name for the window's title bar.
  211.                 */
  212.                LockLine(CommDoc->hParentBlock,CommDoc->ParentOffset,CommDoc->ParentLineID,&BlockPtr,&LinePtr);
  213.                lpsz = (char far *) ( ((char far *)LinePtr) +
  214.                 sizeof(TypLine)+ sizeof(TypGroup) ) ;
  215.                mylstrncpy(group,lpsz,MAXGROUPNAME);
  216.                sprintf(mybuf,"%s (%u articles)",group,CommDoc->TotalLines);
  217.                SetWindowText(CommDoc->hDocWnd,mybuf);
  218.  
  219.                /* If we have information from NEWSRC on the highest-
  220.                 * numbered article previously seen, position the window
  221.                 * so the new articles can be seen without scrolling.
  222.                 */
  223.  
  224.                PrevHighArt = ((TypGroup far *)(lpsz - sizeof(TypGroup)))->HighestPrevSeen;
  225.                GlobalUnlock(BlockPtr->hCurBlock);
  226.  
  227.                if(PrevHighArt && CommDoc->TotalLines > CommDoc->ScYLines
  228.                  && !CommDoc->TopScLineID) {
  229.                   TopOfDoc(CommDoc,&BlockPtr,&LinePtr);
  230.                   found = FALSE;
  231.                   lineord = 0;
  232.                   do {
  233.                      MyArtPtr = (TypArticle far *)((char far *)LinePtr + sizeof(TypLine));
  234.                      if(MyArtPtr->Number > PrevHighArt) {
  235.                         found = TRUE;
  236.                         break;
  237.                      }
  238.                      if(!NextLine(&BlockPtr,&LinePtr)) break;
  239.                      lineord++;
  240.                   } while(!found);
  241.  
  242.                   /* If the line is in the last screen's worth of lines, back
  243.                    * up the pointer so it points to the first line of the last
  244.                    * screen.
  245.                    */
  246.                   if(found) {
  247.                      AdjustTopSc(BlockPtr,LinePtr);
  248. #if 0
  249.                         while(lineord > CommDoc->TotalLines - CommDoc->ScYLines) {
  250.                         PrevLine(&BlockPtr,&LinePtr);
  251.                         lineord--;
  252.                      }
  253.                      UnlockLine(BlockPtr,LinePtr,&(CommDoc->hCurTopScBlock),
  254.                        &(CommDoc->TopScOffset),&(CommDoc->TopScLineID));
  255.                      CommDoc->TopLineOrd = lineord;
  256. #endif
  257.                   } else {
  258.                      UnlockLine(BlockPtr,LinePtr,&hBlock,&Offset,&MyLineID);
  259.                   }
  260.                }
  261.                InvalidateRect(CommDoc->hDocWnd,NULL,FALSE);
  262.             } else {
  263.                artnum = 0;
  264.                sscanf(CommLineIn,"%ld",&artnum);
  265.                artptr = (TypArticle *) (artline + sizeof(TypLine));
  266.                if(artnum) {
  267.                   LockLine(CommDoc->hParentBlock,CommDoc->ParentOffset,CommDoc->ParentLineID,&BlockPtr,&LinePtr);
  268.                   artptr->Number  = artnum;
  269.                   artptr->Seen    = (char)
  270.                     WasArtSeen(artnum,(TypGroup far *)( ((char far *)LinePtr) + sizeof(TypLine) ) );
  271.                   artptr->Selected= FALSE ;
  272.                   artptr->ArtDoc  = (TypDoc *) NULL;
  273.                   UnlockLine(BlockPtr,LinePtr,&(CommDoc->hParentBlock),&(CommDoc->ParentOffset),&(CommDoc->ParentLineID));
  274.  
  275.                   /* Skip past the leading article number and space. */
  276.  
  277.                   for(cptr=CommLineIn; isdigit(*cptr); cptr++);
  278.                   for(;*cptr == ' ';cptr++);
  279.  
  280.                   /* Copy the rest of the received into the line
  281.                    * to be placed in the textblock.
  282.                    * Locate the place in the document to which we
  283.                    * are adding lines, and add this new line.
  284.                    */
  285.                   cdest = artline+sizeof(TypLine)+sizeof(TypArticle);
  286.                   for(artptr->NameLen=0;*(cdest++) = *(cptr++);
  287.                     (artptr->NameLen)++);
  288.                   *cdest = ' ';
  289.                   mylen = (cdest-artline) + sizeof(int);
  290.                   mylen += mylen%2;
  291.                   ((TypLine *)artline)->length = mylen;
  292.                   ((TypLine *)artline)->LineID = NextLineID++;
  293.                   *( (int *) (artline+mylen-sizeof(int)) ) = mylen;
  294.                   LockLine(CommDoc->hCurAddBlock,CommDoc->AddOffset,CommDoc->AddLineID,&BlockPtr,&LinePtr);
  295.                   AddLine((TypLine *)artline,&BlockPtr,&LinePtr);
  296.                   UnlockLine(BlockPtr,LinePtr,&(CommDoc->hCurAddBlock),
  297.                    &(CommDoc->AddOffset),&(CommDoc->AddLineID));
  298.  
  299.                   /* Cause the window to be repainted.
  300.                    * Also, every UPDATE_TITLE_FREQ lines, update the
  301.                    * window title to let the user know how far we
  302.                    * have gotten.
  303.                    */
  304.                   InvalidateRect(CommDoc->hDocWnd,NULL,FALSE);
  305.                   if((++RcvLineCount)%UPDATE_TITLE_FREQ == 0) {
  306.                      sprintf(mybuf,"Retrieving %uth article of ",RcvLineCount);
  307.                      LockLine(CommDoc->hParentBlock,CommDoc->ParentOffset,CommDoc->ParentLineID,&BlockPtr,&LinePtr);
  308.                      lpsz = (char far *) ( ((char far *)LinePtr) +
  309.                       sizeof(TypLine)+ sizeof(TypGroup) ) ;
  310.                      lstrcat(mybuf,lpsz);
  311.                      SetWindowText(CommDoc->hDocWnd,mybuf);
  312.                      GlobalUnlock(BlockPtr->hCurBlock);
  313.                  /*
  314.                   *  if(++TimesWndUpdated <= MAX_IMMEDIATE_UPDATE) {
  315.                   *     InvalidateRect(CommDoc->hDocWnd,NULL,FALSE);
  316.                   *  }
  317.                   */
  318.                      UpdateWindow(CommDoc->hDocWnd);
  319.                   }
  320.                }
  321.             }
  322.  
  323.             break;
  324.  
  325.          case ST_IN_GROUP:
  326.             break;
  327.  
  328.          case ST_ARTICLE_RESP:
  329.             retcode = 0;
  330.             sscanf(CommLineIn,"%d",&retcode);
  331.             if(retcode < 100) break;
  332.             CommState = ST_REC_ARTICLE;
  333.             break;
  334.  
  335.          case ST_REC_ARTICLE:
  336.             if(strcmp(CommLineIn,".") == 0) {
  337.                CommState = ST_IN_GROUP;
  338.                CommBusy = FALSE;
  339.                LockLine(CommDoc->hParentBlock,CommDoc->ParentOffset,CommDoc->ParentLineID,&BlockPtr,&LinePtr);
  340.                lpsz = (char far *) ( ((char far *)LinePtr) +
  341.                 sizeof(TypLine)+ sizeof(TypArticle) ) ;
  342.                mylstrncpy(group,lpsz,MAXGROUPNAME);
  343.                sprintf(mybuf,"%s (%u lines)",group,CommDoc->TotalLines);
  344.                SetWindowText(CommDoc->hDocWnd,mybuf);
  345.                InvalidateRect(CommDoc->hDocWnd,NULL,FALSE);
  346.                GlobalUnlock(BlockPtr->hCurBlock);
  347.  
  348.                /* Skip to the first line of the text of the article
  349.                 * and make sure it's visible on the screen.  This is
  350.                 * so that the user doesn't have to have the first
  351.                 * screen filled with a lengthy, worthless header.
  352.                 */
  353.                if(CommDoc->TotalLines > CommDoc->ScYLines
  354.                  && !CommDoc->TopScLineID) {
  355.                   TopOfDoc(CommDoc,&BlockPtr,&LinePtr);
  356.                   found = FALSE;
  357.                   do {
  358.                      lpsz = ((char far *)LinePtr + sizeof(TypLine) + sizeof(TypText));
  359.                      if(IsLineBlank(lpsz)) {
  360.                         found = TRUE;
  361.                         break;
  362.                      }
  363.                      if(!NextLine(&BlockPtr,&LinePtr)) break;
  364.                   } while(!found);
  365.                   NextLine(&BlockPtr,&LinePtr);
  366.  
  367.                   /* If the line is in the last screen's worth of lines, back
  368.                    * up the pointer so it points to the first line of the last
  369.                    * screen.
  370.                    */
  371.                   if(found) {
  372.                      AdjustTopSc(BlockPtr,LinePtr);
  373.                   } else {
  374.                      UnlockLine(BlockPtr,LinePtr,&hBlock,&Offset,&MyLineID);
  375.                   }
  376.                }
  377.  
  378.             } else {
  379.                /* Copy this line into an image of a textblock line,
  380.                 * expanding tabs.
  381.                 */
  382.                cdest = artline+sizeof(TypLine)+sizeof(TypText);
  383.                for(col=0,cptr=CommLineIn; *cptr &&
  384.                 col<(MAXINTERNALLINE-3*sizeof(TypLine)-sizeof(TypText)); cptr++) {
  385.                   if(*cptr == '\t') {
  386.                      do {
  387.                         *(cdest++) = ' ';
  388.                      } while (++col & 7);
  389.                   } else {
  390.                      *(cdest++) = *cptr;
  391.                      col++;
  392.                   }
  393.                }
  394.                *(cdest++) = '\0';
  395.  
  396.                mylen = (cdest-artline) + sizeof(int);
  397.                mylen += mylen%2;
  398.                ((TypText *)(artline+sizeof(TypLine)))->NameLen =
  399.                 (cdest-1) - (artline+sizeof(TypLine)+sizeof(TypText));
  400.                ((TypLine *)artline)->length = mylen;
  401.                ((TypLine *)artline)->LineID = NextLineID++;
  402.                *( (int *) (artline+mylen-sizeof(int)) ) = mylen;
  403.                LockLine(CommDoc->hCurAddBlock,CommDoc->AddOffset,CommDoc->AddLineID,&BlockPtr,&LinePtr);
  404.                AddLine((TypLine *)artline,&BlockPtr,&LinePtr);
  405.                UnlockLine(BlockPtr,LinePtr,&(CommDoc->hCurAddBlock),
  406.                 &(CommDoc->AddOffset),&(CommDoc->AddLineID));
  407.                if((CommDoc->TotalLines % UPDATE_ART_FREQ) == 0) {
  408.             InvalidateRect(CommDoc->hDocWnd,NULL,FALSE);  
  409.                }
  410.             }
  411.  
  412.             break;
  413.  
  414.          case ST_POST_WAIT_PERMISSION:
  415.             for(ih=0,found=FALSE; !found && ih<MAXPOSTWNDS; ih++) {
  416.               if(&(PostingDocs[ih]) == CommDoc) {
  417. #ifndef MAC
  418.                  hWndPostEdit = hWndPostEdits[ih];
  419. #else
  420.   /* mrr add here */
  421. #endif
  422.                  found = TRUE;
  423.                  break;
  424.               }
  425.             }
  426.             retcode = 0;
  427.             sscanf(CommLineIn,"%d",&retcode);
  428.             if(retcode <= 0) {
  429.                break;
  430.             } else if(retcode == 340) {
  431.                PostText(ih,DOCTYPE_POSTING);
  432.             } else {
  433.                MessageBox(hWndPostEdit,CommLineIn+4,"Cannot Post Article",
  434.                   MB_OK|MB_ICONEXCLAMATION);
  435.                CommBusy = FALSE;
  436.                CommState = ST_NONE;
  437.             }
  438.  
  439.             break;
  440.  
  441.          case ST_POST_WAIT_END:
  442.             for(ih=0,found=FALSE; !found && ih<MAXPOSTWNDS; ih++) {
  443.               if(&(PostingDocs[ih]) == CommDoc) {
  444. #ifndef MAC
  445.                  hWndPostEdit = hWndPostEdits[ih];
  446. #else
  447.   /* mrr add here */
  448. #endif
  449.                  found = TRUE;
  450.                  break;
  451.               }
  452.             }
  453.             retcode = 0;
  454.             sscanf(CommLineIn,"%d",&retcode);
  455.             if(retcode == 441 || retcode == 440) {
  456.                cptr = "Posting Failed";
  457.                mbcode = MB_OK|MB_ICONEXCLAMATION;
  458.                done = TRUE;
  459.             } else if(retcode == 240) {
  460.                cptr = "Article Posted OK";
  461.                mbcode = MB_OK;
  462.                done = TRUE;
  463.             }
  464.             if(done) {
  465.                CommBusy = FALSE;
  466.                CommState = ST_NONE;
  467.                MessageBox(hWndPostEdit,CommLineIn+4,cptr,mbcode);
  468.             }
  469.             break;
  470.  
  471.          case ST_MAIL_WAIT_PERMISSION:
  472.             for(ih=0,found=FALSE; !found && ih<MAXMAILWNDS; ih++) {
  473.               if(&(MailDocs[ih]) == CommDoc) {
  474. #ifndef MAC
  475.                  hWndPostEdit = hWndMailEdits[ih];
  476. #else
  477.   /* mrr add here */
  478. #endif
  479.                  found = TRUE;
  480.                  break;
  481.               }
  482.             }
  483.             retcode = 0;
  484.             sscanf(CommLineIn,"%d",&retcode);
  485.             if(retcode <= 0) {
  486.                break;
  487.             } else if(retcode == 350) {
  488.                PostText(ih,DOCTYPE_MAIL);
  489.             } else {
  490.                MessageBox(hWndPostEdit,CommLineIn+4,"Cannot Mail Message",
  491.                   MB_OK|MB_ICONEXCLAMATION);
  492.                CommBusy = FALSE;
  493.                CommState = ST_NONE;
  494.             }
  495.  
  496.             break;
  497.  
  498.          case ST_MAIL_WAIT_END:
  499.             for(ih=0,found=FALSE; !found && ih<MAXMAILWNDS; ih++) {
  500.               if(&(MailDocs[ih]) == CommDoc) {
  501. #ifndef MAC
  502.                  hWndPostEdit = hWndMailEdits[ih];
  503. #else
  504.   /* mrr add here */
  505. #endif
  506.                  found = TRUE;
  507.                  break;
  508.               }
  509.             }
  510.             retcode = 0;
  511.             sscanf(CommLineIn,"%d",&retcode);
  512.             if(retcode == 451 || retcode == 450) {
  513.                cptr = "Mailing Failed";
  514.                mbcode = MB_OK|MB_ICONEXCLAMATION;
  515.                done = TRUE;
  516.             } else if(retcode == 250) {
  517.                cptr = "Message sent OK";
  518.                mbcode = MB_OK;
  519.                done = TRUE;
  520.             }
  521.             if(done) {
  522.                CommBusy = FALSE;
  523.                CommState = ST_NONE;
  524.                MessageBox(hWndPostEdit,CommLineIn+4,cptr,mbcode);
  525.             }
  526.             break;
  527.  
  528.       case ST_GROUP_REJOIN:
  529.          CommState = ST_ARTICLE_RESP;
  530.          break;
  531.       }
  532.    }
  533. }
  534.  
  535. /*-- function WasArtSeen ---------------------------------------------
  536.  *
  537.  *  Determines whether (according to the information in a TypGroup entry)
  538.  *  a given article number was seen.
  539.  *
  540.  *  Returns TRUE iff the article has been seen.
  541.  */
  542. BOOL
  543. WasArtSeen(ArtNum,GroupPtr)
  544. long int ArtNum;
  545. TypGroup far *GroupPtr;
  546. {
  547.    TypRange far *RangePtr = (TypRange far *) ((char far *)
  548.       GroupPtr + RangeOffset(GroupPtr->NameLen));
  549.    int nr;
  550.  
  551.    for(nr=0; nr < GroupPtr->nRanges; nr++) {
  552.       if(ArtNum >= RangePtr->First && ArtNum <= RangePtr->Last) {
  553.          return(TRUE);
  554.       } else {
  555.          RangePtr++;
  556.       }
  557.    }
  558.    return(FALSE);
  559. }
  560.  
  561. /*--- function mylstrncmp -----------------------------------------------
  562.  *
  563.  *   Just like strncmp, except takes long pointers.
  564.  */
  565. int
  566. mylstrncmp(ptr1,ptr2,len)
  567. char far *ptr1;
  568. char far *ptr2;
  569. int len;
  570. {
  571.    for(;len--;ptr1++,ptr2++) {
  572.       if(*ptr1 > *ptr2) {
  573.          return(1);
  574.       } else if(*ptr1 < *ptr2) {
  575.          return(-1);
  576.       }
  577.    }
  578.    return(0);
  579. }
  580.  
  581. /*--- function mylstrncpy -----------------------------------------------
  582.  *
  583.  *   Just like strncpy, except takes long pointers.
  584.  */
  585. char far *
  586. mylstrncpy(ptr1,ptr2,len)
  587. char far *ptr1;
  588. char far *ptr2;
  589. int len;
  590. {
  591.    char far *targ = ptr1;
  592.  
  593.    for(; --len && *ptr2; ptr1++,ptr2++) {
  594.       *ptr1 = *ptr2;
  595.    }
  596.    *ptr1 = '\0';
  597.    return(targ);
  598. }
  599.  
  600. #if 0
  601. /*--- function lstrcmpnoblank ------------------------------------------
  602.  *
  603.  *   Like strcmp, except takes long pointers and also stops at
  604.  *   the first blank.
  605.  */
  606. int
  607. lstrcmpnoblank(str1,str2)
  608. char far **str1;
  609. char far **str2;
  610. {
  611.    register char far *s1=*str1, far *s2=*str2;
  612.  
  613.     for(;*s1 && *s2 && *s1!=' ' && *s2!=' '; s1++,s2++) {
  614.         if(*s1 > *s2) {
  615.             return (1);
  616.         } else if(*s1 < *s2) {
  617.             return (-1);
  618.         }
  619.     }
  620.     if(*s1 == *s2) {
  621.         return(0);
  622.     } else if(*s1) {
  623.         return(1);
  624.     } else {
  625.         return(-1);
  626.     }
  627. }
  628. #endif
  629.